import 'package:flutter/material.dart';
import 'package:flutter_custom_view/src/pan_gesture_detector.dart';

///创建时间：2021年1月9日
///作者：黄云音
///描述：

typedef SelectRectangleColor = void Function(double h, double s);

class RectangleColorPicker extends StatefulWidget {

  final Color initialColor;
  final SelectRectangleColor? onCallBack;
  final SelectRectangleColor? onCallBackEnd;
  final double? selectRadius;
  final double? borderWidth;
  final bool? scrollChild;
  final double? aspectRatio;
  final double? padding;

  const RectangleColorPicker({
    Key? key,
    required this.initialColor,
    this.onCallBack,
    this.onCallBackEnd,
    this.selectRadius = 32,
    this.borderWidth = 3,
    this.scrollChild = false,
    this.aspectRatio = 150 / 360,
    this.padding=0,
  }) : super(key: key);

  @override
  _RectangleColorPickerState createState() => _RectangleColorPickerState();
}

class _RectangleColorPickerState extends State<RectangleColorPicker> {
  late Color colorRgb;
  double _top = 0.0;
  double _left = 0.0;
  double? _hue = 0.0;
  double? _saturation = 0.0;
  double? _colorWidth;
  double? _colorHeight;
  bool isOnPan = false;
  bool isFirst = true;

  Color get _color {
    return HSVColor.fromAHSV(1.0, _hue!, _saturation!, 1.0).toColor();
  }

  @override
  void initState() {
    super.initState();
    HSVColor hsvColor = HSVColor.fromColor(widget.initialColor);
    colorRgb = HSVColor.fromAHSV(
            1.0, hsvColor.hue, hsvColor.saturation, hsvColor.value)
        .toColor();
  }

  @override
  void didUpdateWidget(covariant RectangleColorPicker oldWidget) {
    if (oldWidget.initialColor != widget.initialColor && !isOnPan) {
      _updateColor(widget.initialColor);
    }
    super.didUpdateWidget(oldWidget);
  }

  _updateColor(Color color) {
    setState(() {
      HSVColor hsvColor = HSVColor.fromColor(color);
      colorRgb = HSVColor.fromAHSV(
              1.0, hsvColor.hue, hsvColor.saturation, hsvColor.value)
          .toColor();
      double radius = widget.selectRadius!;
      double scope = _colorWidth! * 20 / 360;
      double centerScope = (_colorWidth! - widget.selectRadius! * 2);
      if (isOnPan) {
        ///拖动的情况下
        if ((radius + centerScope * 0 / 6 - scope < _left && _left < radius + centerScope * 0 / 6 + scope) && (_top < 5 + radius)) {
          return null;
        } else if ((radius + centerScope * 1 / 6 - scope < _left && _left < radius + centerScope * 1 / 6 + scope) && (_top < 5 + radius)) {
          return null;
        } else if ((radius + centerScope * 2 / 6 - scope < _left && _left < radius + centerScope * 2 / 6 + scope) && (_top < 5 + radius)) {
          return null;
        } else if ((radius + centerScope * 3 / 6 - scope < _left && _left < radius + centerScope * 3 / 6 + scope) && (_top < 5 + radius)) {
          return null;
        } else if ((radius + centerScope * 4 / 6 - scope < _left && _left < radius + centerScope * 4 / 6 + scope) && (_top < 5 + radius)) {
          return null;
        }
          else if ((radius + centerScope * 5 / 6 - scope < _left && _left < radius + centerScope * 5 / 6 + scope) && (_top < 5 + radius)) {
          return null;
        }
          else if ((radius + centerScope * 6 / 6 - scope < _left && _left < radius + centerScope * 6 / 6 + scope) && (_top < 5 + radius)) {
          return null;
        }
          else {
            ///拖动，并且不在特殊点的情况下
          if(HSVColor.fromColor(color).hue==0.0){
             // _left = widget.selectRadius! + ((_colorWidth! - widget.selectRadius! * 2) * hsvColor.hue) / 360;
            _top = widget.selectRadius! +
                ((_colorHeight! - widget.selectRadius! * 2) *
                    (1 - hsvColor.saturation));
            print("----拖动，HSVColor.fromColor(color).hue==0.0-----1");
          }else{
            print("---拖动，并且不在特殊点的情况下");
            _left = widget.selectRadius! + ((_colorWidth! - widget.selectRadius! * 2) * hsvColor.hue) / 360;
            _top = widget.selectRadius! + ((_colorHeight! - widget.selectRadius! * 2) * (1 - hsvColor.saturation));
          }
        }
      } else {
        ///不拖动的情况下
        print("==============不拖动的情况下");
        _left = widget.selectRadius! + ((_colorWidth! - widget.selectRadius! * 2) * hsvColor.hue) / 360;
        _top = widget.selectRadius! + ((_colorHeight! - widget.selectRadius! * 2) * (1 - hsvColor.saturation));
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding:  EdgeInsets.all(widget.padding!),
      child: Center(
        child: LayoutBuilder(
            builder: (BuildContext context, BoxConstraints constraints) {
          if(constraints.maxWidth*widget.aspectRatio!<constraints.maxHeight){
            _colorWidth = constraints.maxWidth;
            _colorHeight = constraints.maxWidth*widget.aspectRatio!;
          }else{
            _colorWidth = constraints.maxHeight/widget.aspectRatio!;
            _colorHeight = constraints.maxHeight;
          }
          HSVColor hsvColor = HSVColor.fromColor(colorRgb);
          if(hsvColor.hue!=360&&isFirst){
            _left = widget.selectRadius! + ((_colorWidth! - widget.selectRadius! * 2) * hsvColor.hue) / 360;
            isFirst = false;
            print("isFirst = false");
          }
          _top = widget.selectRadius! + ((_colorHeight! - widget.selectRadius! * 2) * (1 - hsvColor.saturation));
          return Stack(
            alignment: Alignment.center,
            children: [
              ClipRRect(
                borderRadius: BorderRadius.circular(widget.selectRadius!),
                child: GestureDetector(
                  child: ColorRect(
                    colorHeight: _colorHeight!,
                    colorWidth: _colorWidth!,
                    selectRadius: widget.selectRadius!,
                  ),
                ),
              ),
              Container(
                child: ColorThumb(
                  top: _top,
                  left: _left,
                  selectRadius: widget.selectRadius!,
                  borderWidth: widget.borderWidth!,
                  color: colorRgb,
                ),
              ),
              PanGestureDetector(
                disposition: (downEvent) {
                  ///解决手势冲突问题
                  if (widget.scrollChild!) {
                    var dx = downEvent.localPosition.dx;
                    var dy = downEvent.localPosition.dy;
                    bool inHorizontalAxis = dx > _left - widget.selectRadius! / 2 && dx < _left + widget.selectRadius! / 2;
                    bool inVerticalAxis = dy > _top - widget.selectRadius! / 2 && dy < _top + widget.selectRadius! / 2;
                    if (inHorizontalAxis && inVerticalAxis) {
                      return PanGestureDisposition.intercept;
                    }
                    return PanGestureDisposition.abort;
                  } else {
                    return PanGestureDisposition.intercept;
                  }
                },
                onPanStart: (DragStartDetails detail) {
                  isOnPan = true;
                  var localPosition = detail.localPosition;
                  buildSetState(localPosition, context);
                  HSVColor hsvColor = HSVColor.fromColor(_color);
                  widget.onCallBack?.call(
                    hsvColor.hue,
                    hsvColor.saturation,
                  );
                  colorRgb = _color;
                },
                onPanUpdate: (DragUpdateDetails detail) {
                  isOnPan = true;
                  //获取当前触摸点的局部坐标
                  var localPosition = detail.localPosition;
                  buildSetState(localPosition, context);
                  HSVColor hsvColor = HSVColor.fromColor(_color);
                  widget.onCallBack?.call(
                    hsvColor.hue,
                    hsvColor.saturation,
                  );
                  colorRgb = _color;
                },
                onPanEnd: (DragEndDetails detail) {
                  HSVColor hsvColor = HSVColor.fromColor(_color);
                  widget.onCallBackEnd?.call(
                    hsvColor.hue,
                    hsvColor.saturation,
                  );
                  colorRgb = _color;
                  setState(() {
                    colorRgb = _color;
                  });

                  ///延迟重置开关，等界面更新后再重置
                  Future.delayed(Duration(milliseconds: 100),(){
                    isOnPan = false;
                  });

                },
                child: Container(
                  width: _colorWidth!,
                  height: _colorHeight!,
                ),
              )
            ],
          );
        }),
      ),
    );
  }

  void buildSetState(Offset localPosition, BuildContext context) {
    return setState(() {
      _left = localPosition.dx;
      _top = localPosition.dy;
      if (_left < widget.selectRadius!) {
        _left = widget.selectRadius!;
        _hue = 0;
      } else if (widget.selectRadius! <= _left && _left <= _colorWidth! - widget.selectRadius!) {
        _hue = 360 * (_left - widget.selectRadius!) / (_colorWidth! - widget.selectRadius! * 2);
      } else if (_left > _colorWidth! - widget.selectRadius!) {
        _left = (_colorWidth! - widget.selectRadius!);
        _hue = 360;
      }

      double radius = widget.selectRadius!;
      double scope = _colorWidth! * 10 / 360;
      double centerScope = (_colorWidth! - widget.selectRadius! * 2);
      if ((radius + centerScope * 0 / 6 - scope < _left && _left < radius + centerScope * 0 / 6 + scope) && (_top < 5)) {
        _left = radius + centerScope * 0 / 6;
        _top = 0;
      } else if ((radius + centerScope * 1 / 6 - scope < _left && _left < radius + centerScope * 1 / 6 + scope) && (_top < 5)) {
        _left = radius + centerScope * 1 / 6;
        _top = 0;
      } else if ((radius + centerScope * 2 / 6 - scope < _left && _left < radius + centerScope * 2 / 6 + scope) && (_top < 5)) {
        _left = radius + centerScope * 2 / 6;
        _top = 0;
      } else if ((radius + centerScope * 3 / 6 - scope < _left && _left < radius + centerScope * 3 / 6 + scope) && (_top < 5)) {
        _left = radius + centerScope * 3 / 6;
        _top = 0;
      } else if ((radius + centerScope * 4 / 6 - scope < _left && _left < radius + centerScope * 4 / 6 + scope) && (_top < 5)) {
        _left = radius + centerScope * 4 / 6;
        _top = 0;
      } else if ((radius + centerScope * 5 / 6 - scope < _left && _left < radius + centerScope * 5 / 6 + scope) && (_top < 5)) {
        _left = radius + centerScope * 5 / 6;
        _top = 0;
      } else if ((radius + centerScope * 6 / 6 - scope < _left && _left < radius + centerScope * 6 / 6 + scope) && (_top < 5)) {
        _left = radius + centerScope * 6 / 6;
        _top = 0;
      }

      if (_top <= widget.selectRadius!) {
        _top = widget.selectRadius!;
        _saturation = 1.0;
      } else if (widget.selectRadius! <= _top && _top <= _colorHeight! - widget.selectRadius!) {
        _saturation = 1 - (_top - widget.selectRadius!) / (_colorHeight! - widget.selectRadius! * 2);
      } else if (_top > _colorHeight! - widget.selectRadius!) {
        _top = _colorHeight! - widget.selectRadius!;
        _saturation = 0.0;
      }
    });
  }
}

class ColorRect extends StatelessWidget {
  const ColorRect({
    Key? key,
    required double colorHeight,
    required double colorWidth,
    required double selectRadius,
  })  : _colorHeight = colorHeight,
        _colorWidth = colorWidth,
        _selectRadius = selectRadius,
        super(key: key);

  final double _colorHeight;
  final double _colorWidth;
  final double _selectRadius;

  @override
  Widget build(BuildContext context) {
    return Container(
      height: _colorHeight,
      width: _colorWidth,
      alignment: Alignment.center,
      child: Stack(
        alignment: Alignment.center,
        children: [
          Container(
            padding: EdgeInsets.symmetric(horizontal: _selectRadius),
            child: DecoratedBox(
              child: Container(height: _colorHeight, width: _colorWidth),
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  begin: Alignment.centerLeft,
                  end: Alignment.centerRight,
                  stops: [
                    0 * 60 / 360,
                    1 * 60 / 360,
                    2 * 60 / 360,
                    3 * 60 / 360,
                    4 * 60 / 360,
                    5 * 60 / 360,
                    6 * 60 / 360
                  ],
                  colors: [
                    Color.fromARGB(255, 255, 0, 0),
                    Color.fromARGB(255, 255, 255, 0),
                    Color.fromARGB(255, 0, 255, 0),
                    Color.fromARGB(255, 0, 255, 255),
                    Color.fromARGB(255, 0, 0, 255),
                    Color.fromARGB(255, 255, 0, 255),
                    Color.fromARGB(255, 255, 0, 0),
                  ],
                ),
              ),
            ),
          ),
          Container(
            alignment: Alignment.centerLeft,
            height: _colorHeight,
            width: _colorWidth,
            child: Container(
              color: Color.fromARGB(255, 255, 0, 0),
              width: _selectRadius + 1,
            ),
          ),
          Container(
            alignment: Alignment.centerRight,
            height: _colorHeight,
            width: _colorWidth,
            child: Container(
              color: Color.fromARGB(255, 255, 0, 0),
              width: _selectRadius + 1,
            ),
          ),
          Container(
            padding: EdgeInsets.only(bottom: _selectRadius / 2),
            alignment: Alignment.center,
            height: _colorHeight,
            width: _colorWidth,
            child: Container(
              alignment: Alignment.center,
              decoration: BoxDecoration(
                gradient: LinearGradient(
                    begin: Alignment.bottomCenter,
                    end: Alignment.topCenter,
                    colors: [Colors.white, Colors.transparent]
                    // colors: list.map((e) => e.opacityColor).toList(),
                    // stops: list.map((e) => e.point).toList()
                    ),
              ),
            ),
          ),
          Container(
            alignment: Alignment.bottomCenter,
            height: _colorHeight,
            width: _colorWidth,
            child: Container(
              color: Colors.white,
              height: _selectRadius / 2 + 1,
            ),
          ),
        ],
      ),
    );
  }
}

class GradientModel {
  final Color opacityColor;
  final double point;

  GradientModel({required this.opacityColor, required this.point});
}

class ColorThumb extends StatelessWidget {
  const ColorThumb({
    Key? key,
    required double top,
    required double selectRadius,
    required double borderWidth,
    required double left,
    required Color color,
  })  : _top = top,
        _selectRadius = selectRadius,
        _borderWidth = borderWidth,
        _left = left,
        _color = color,
        super(key: key);

  final double _top;
  final double _selectRadius;
  final double _borderWidth;
  final double _left;
  final Color _color;

  @override
  Widget build(BuildContext context) {
    return Positioned(
      top: _top - _selectRadius,
      left: _left - _selectRadius,
      child: GestureDetector(
        child: Container(
          width: _selectRadius * 2,
          height: _selectRadius * 2,
          alignment: Alignment.center,
          padding: EdgeInsets.all(_borderWidth),
          child: Container(
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(100),
              color: _color,
            ),
          ),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(100),
            color: Colors.white,
            border: Border.all(width: 1, color: Colors.white),
            boxShadow: [
              BoxShadow(
                blurRadius: 5.0, //阴影范围
                spreadRadius: 0.001, //阴影浓度
                color: Colors.black, //阴影颜色
              ),
            ],
          ),
        ),
      ),
    );
  }
}
